package com.pj.compose.ui.compose

import android.graphics.Rect
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.input.key.*
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.text.input.*
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.text.isDigitsOnly
import com.blankj.utilcode.util.LogUtils

enum class FocusState {
    Active,
    /*ActiveParent,
    Captured,
    Deactivated,
    DeactivatedParent,
    Inactive*/
}

//onCompleted函数是：输入完成后该干啥，一般是带上手机号去后台做验证。
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun SmsCodeCompose(onCompleted: (String) -> Unit, modifier: Modifier = Modifier) {
    //记住输入的值，compose重绘的时候会丢失，remember会在这个socpe范围内记住这个值
    var text by remember { mutableStateOf("") }
//获取输入textInputService服务。 LocalTextInputService.current这个是compose库帮我们初始化的
    val textInputService = LocalTextInputService.current
    val focusRequester by remember { mutableStateOf(FocusRequester()) }
//这两个是自己搞的状态，其实可以不用
    var focusState by remember { mutableStateOf(FocusState.Active) }
    var isKeyboardShow by remember { mutableStateOf(true) }
    var inputSession: TextInputSession? = null
    //使用canvas 组件来实现，按键焦点都在modifier实现
    Box(
        modifier = modifier
            //注册点击事件处理函数，在这边获取焦点
            .pointerInput("key") {
                detectTapGestures(onTap = {
                    //请求焦点
                    focusRequester.requestFocus()
                    if (focusState == FocusState.Active && !isKeyboardShow) {
                        //显示键盘
                        inputSession?.showSoftwareKeyboard()
                        //这个状态其实无所谓，showSoftwareKeyboard调用多次也没关系
                        isKeyboardShow = true
                    }
                })
            }
    ) {
        Canvas(
            modifier = Modifier.width((40*6).dp)
                .focusRequester(focusRequester)
                .onKeyEvent {
                    if (it.type == KeyEventType.KeyDown && it.key == Key.Backspace) {
//                        LogUtils.d("按键监听: ${it.key.keyCode} ")
                        text = text.dropLast(1)
                    }
                    false
                }
                .onFocusChanged { it ->
                    if (it.isFocused) {
                        //保存焦点状态，方便用户隐藏键盘以后再弹出来
                        focusState = FocusState.Active
                        //开启按键输入
                        inputSession = textInputService?.startInput(
                            //TextFieldValue 这个玩意还挺复杂的，在textfield 等组件可以直接通过他控制光标
                            value = TextFieldValue(""),
                            //设置键盘类型和右下角那个“确定”键的功能
                            imeOptions = ImeOptions.Default.copy(
                                keyboardType = KeyboardType.Number, imeAction = ImeAction.Done
                            ),
                            //接收按键消息，所有键盘事件都是EditCommand接口的子类
                            onEditCommand = { command ->
                                //command 为啥是一个list，我猜测是可能有组合按键？遗留！！！！
                                command.forEach {
                                    when (it) {
                                        //用户隐藏了键盘
                                        is FinishComposingTextCommand -> isKeyboardShow = false
                                        //按键command，其中的text就是按下的键
                                        is CommitTextCommand -> if (it.text.isDigitsOnly()) text += it.text
                                        //删除命令
                                        is BackspaceCommand -> text = text.dropLast(1)
                                        // else就懒得管了，还有不少command，比如移动输入光标的，等等
                                        else -> LogUtils.d("按键${it}")
                                    }
                                    //输入完成
                                    if (text.length == 6) onCompleted(text)
                                }
                            },
                            //这个就是键盘右下角那个特殊的按键事件，比如搜索，完成，发送等等
                            onImeActionPerformed = {
                                if (it == ImeAction.Done) {
                                    inputSession?.hideSoftwareKeyboard()
                                }
                            })
                        if (!isKeyboardShow) {
                            inputSession?.showSoftwareKeyboard()
                        }
                    }
                }
                .focusModifier()

        ) {
            //开始画界面，额。。。大小是写死的，可以获取canvas的大小做成动态的。这就当作初版吧
            drawIntoCanvas { canvas ->
                //底线画笔
                val grayPaint = Paint()
                grayPaint.color = Color.LightGray
                grayPaint.style = PaintingStyle.Fill
                //底线有焦点时候的画笔
                val orangePaint = Paint()
                orangePaint.color = Color(0xFFE53935)
                orangePaint.style = PaintingStyle.Fill
                //文字画笔。
                val textPaint = android.graphics.Paint()
                //textPaint.strokeWidth=1f 设置描边可以加粗字体
                textPaint.isAntiAlias = true
                textPaint.style = android.graphics.Paint.Style.FILL_AND_STROKE
                textPaint.color = Color.Black.toArgb()
                textPaint.textSize = 24.sp.toPx()
                //坐标啥的就不多说了
                val rectText = Rect()
                var left = 0f
                var right = 30.dp.toPx()
                for (index in 0..5) {
                    canvas.drawRoundRect(
                        left, 38.dp.toPx(), right, 40.dp.toPx(), 1.dp.toPx(), 1.dp.toPx(),
                        //根据输入文字的长度处理焦点。
                        if (index == text.lastIndex + 1) orangePaint else grayPaint
                    )
                    //draw 文字
                    if (index < text.length) {
                        textPaint.getTextBounds(text, index, index + 1, rectText)
                        canvas.nativeCanvas.drawText(
                            text,
                            index,
                            index + 1,
                            left + rectText.width().toFloat() / 2,
                            20.dp.toPx(),
                            textPaint
                        )
                    }
                    left += 40.dp.toPx()
                    right += 40.dp.toPx()
                }
            }
        }
    }
}